﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using SDFL.Core;
using System.Diagnostics;

namespace SysCounterSpy
{
    public partial class FrmMainForm : Form
    {

        private string machineName = System.Environment.MachineName;
        SDFL.ExceptionHandling.ExceptionManagerImpl exHandler = new SDFL.ExceptionHandling.ExceptionManagerImpl();
        PerfCounters counters = null;

        public FrmMainForm()
        {
            InitializeComponent();
            GetMachineName();
            LoadSettings();
        }

        private void FrmMainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            // save our window position
            SaveSettings();           
        }

        private void FrmMainForm_Load(object sender, EventArgs e)
        {
            // do our safety checks here
            // if we're trying to monitor a remote computer
            if (!this.machineName.Equals(System.Environment.MachineName))
            {
                if (!SDFL.Remoting.Helper.VerifyRemoteMachineStatus(this.machineName))
                {
                    exHandler.HandleException(String.Format("Unable to access computer '{0}'\r\nPlease check spelling and verify this computer is connected to the network", this.machineName));
                    Close();
                    return;
                }
            }

            try
            {
                counters = PerfCounters.GetPerfCountersInstance(this.machineName);

                // there can be multiple network interfaces, accordingly, there are multiple counters,           
                // for each nic card, create a corresponding status bar label
                for (int i = 0; i < counters.nicCounters.Length; i++)
                {
                    ssStatusBar.Items.Add(CreateNICLabel(counters.nicCounters[i], i));
                }
            }
            catch (Exception ex)
            {
                exHandler.HandleException(String.Format("Unable to access computer '{0}'\r\nPlease check spelling and verify this computer is connected to the network", this.machineName));
                Close();
            }

            SetFormWidth();
            
            // set the form text
            this.Text = String.Format("{0} [{1}]", Application.ProductName, this.machineName);
            
            // our Timer starts out Enabled==false, so if we get an exception while initializing counters
            // we don't get *more* from each Timer.Tick
            tTimer.Enabled = true;
        }

        private void tTimer_Tick(object sender, EventArgs e)
        {
            try
            {
                tsCPU.Text = String.Format("{0:##0}%",  counters.cpuCounter.NextValue());

                //tsRAM.Text = String.Format("{0} MB", ramCounter.NextValue());
                tsRAM.Text = String.Format("{0:##0}%", counters.ramCounter.NextValue());
                tsPage.Text = String.Format("{0:##0}%", counters.pageCounter.NextValue());

                for (int i = 0; i < counters.nicCounters.Length; i++)
                {
                    ssStatusBar.Items[String.Format("tsNIC{0}", i)].Text = String.Format("{0:####0KB/s}", counters.nicCounters[i].NextValue() / 1024);
                }
            }
            catch (Exception ex)
            {
                // remote computer might have become unavailable; 
                // show exception and close this application
                tTimer.Enabled = false;
                exHandler.HandleException(ex);
                Close();
            }
        }

        // Get cmdArgs
        private void GetMachineName()
        {
            string[] cmdArgs = System.Environment.GetCommandLineArgs();
            
            if ((cmdArgs != null) && (cmdArgs.Length > 1))
            { 
                this.machineName = cmdArgs[1]; 
            }
        }

        // create a ToolStripStatusLabel for each network interface
        private ToolStripStatusLabel CreateNICLabel(PerformanceCounter counter, int index)
        {
            ToolStripStatusLabel newLabel = new ToolStripStatusLabel();

            newLabel.AutoSize = false;
            newLabel.Width = 60;
            newLabel.ToolTipText = counter.InstanceName;
            newLabel.Text = string.Empty;
            newLabel.Name = String.Format("tsNIC{0}", index);
            newLabel.TextAlign = ContentAlignment.MiddleRight;
            newLabel.BorderSides = ToolStripStatusLabelBorderSides.All;
            newLabel.BorderStyle = Border3DStyle.SunkenInner;
            newLabel.Height = ssStatusBar.Items[0].Height;

            return newLabel;
        }

        // adjust form width based on number of statusbar labels
        private void SetFormWidth()
        {
            //this.Width = (tsCPU.Width + tsRAM.Width + tsPage.Width);
            int width = 0;
            foreach (ToolStripStatusLabel label in ssStatusBar.Items)
            { width += label.Width + label.Padding.Right; }

            if (ssStatusBar.Padding.Horizontal > 0)
            { width += (ssStatusBar.Padding.Horizontal / 2); }
            this.Width = width;
        }       

        #region config settings
        // Load and save last window position
        // simple way to do it so that we can run multiple instances (one per machine) and still have them all save their position
        private void LoadSettings()
        {
            int iLeft = 0;
            int iTop = 0;

            System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            //System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoaming);
            try
            {
                // TryParse will default to zero on an invalid value
                int.TryParse(ConfigurationManager.AppSettings[String.Format("{0}-Left", this.machineName)], out iLeft);
                int.TryParse(ConfigurationManager.AppSettings[String.Format("{0}-Top", this.machineName)], out iTop);
            }
            finally
            {
                this.Left = iLeft;
                this.Top = iTop;
                config = null;
            }
        }

        private void SaveSettings()
        {
            System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            //System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoaming);
            try
            {
                // remove the previously saved values
                config.AppSettings.Settings.Remove(String.Format("{0}-Left", this.machineName));
                config.AppSettings.Settings.Remove(String.Format("{0}-Top", this.machineName));
                // save our current values
                // this saves to app.config so it may be a permissions issue for non-admin users
                config.AppSettings.Settings.Add(String.Format("{0}-Left", this.machineName), this.Left.ToString());
                config.AppSettings.Settings.Add(String.Format("{0}-Top", this.machineName), this.Top.ToString());
                config.Save(ConfigurationSaveMode.Modified);
            }
            finally
            { config = null; }
        }
        #endregion
    }
}
